package com.woniu.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.woniu.dto.DepositDTO;
import com.woniu.dto.PendingDepositQueryDTO;
import com.woniu.dto.PendingSettleQueryDTO;
import com.woniu.dto.SettleDTO;
import com.woniu.entity.*;
import com.woniu.mapper.*;
import com.woniu.service.FinanceService;
import com.woniu.utils.ResponseEnum;
import com.woniu.utils.ResponseUtil;
import com.woniu.vo.InpatientAppVO;
import com.woniu.vo.InpatientDischargeAppVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class FinanceServiceImpl implements FinanceService {

    @Resource
    private InpatientApplicationMapper applicationMapper;

    @Resource
    private RechargeFeeMapper rechargeFeeMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseUtil payDeposit(DepositDTO dto) {
        // 1. 校验押金是否 >= 1000
        if (dto.getAmount().compareTo(new BigDecimal("1000.00")) < 0) {
            return ResponseUtil.get(ResponseEnum.FAIL, "住院押金至少为1000元");
        }

        // 2. 检查入院申请单 (ia_status) 是否为 '1' (待缴费)
        InpatientApplication app = applicationMapper.selectByPrimaryKey(dto.getApplicationId().longValue());
        if (app == null || !"1".equals(app.getIaStatus())) {
            return ResponseUtil.get(ResponseEnum.FAIL, "缴费失败：该申请单不是'待缴费'状态");
        }

        // 校验病人ID
        if (!dto.getPatientId().equals(app.getIaCaseid())) {
            return ResponseUtil.get(ResponseEnum.FAIL, "病人ID与申请单不匹配");
        }

        // 3. 更新 InpatientRecord 的余额
        int rowsAffected = inpatientRecordMapper.addBalanceToRecord(dto.getPatientId(), dto.getAmount());

        if (rowsAffected == 0) {
            return ResponseUtil.get(ResponseEnum.FAIL, "缴费失败：未找到该患者的在院记录 (hz_status=0)");
        }

        // 4. 记录押金流水
        RechargeFee deposit = new RechargeFee();
        deposit.setPrCaseid(dto.getPatientId());
        deposit.setPrMoney(dto.getAmount());
        deposit.setPrDate(new Date());
        deposit.setPrType("0"); // '0' = 住院押金
        rechargeFeeMapper.insertSelective(deposit);

        // 5. 更新入院申请表 (inpatient_application) 状态为 "2" (完成)
        // 在患者缴纳押金后，需要将入院申请表的状态修改成完成
        InpatientApplication appUpdate = new InpatientApplication();
        appUpdate.setId(dto.getApplicationId());
        appUpdate.setIaStatus("2"); // 2 = 完成
        applicationMapper.updateByPrimaryKeySelective(appUpdate); //

        return ResponseUtil.get(ResponseEnum.OK, "押金缴纳成功");
    }
    @Resource
    private InpatientRecordMapper inpatientRecordMapper; //

    @Resource
    private InpatientDischargeAppMapper dischargeAppMapper; //

    @Resource
    private RefundDetailMapper refundDetailMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseUtil settleDischarge(SettleDTO dto) {

        // 1. 校验出院申请单状态
        InpatientDischargeApp app = dischargeAppMapper.selectByPrimaryKey(dto.getDischargeApplicationId().longValue());
        if (app == null || !dto.getPatientId().equals(app.getOaCaseId())) {
            return ResponseUtil.get(ResponseEnum.FAIL, "结算失败：出院申请单不存在或病人ID不匹配");
        }
        if (app.getOaStatus() != 0) { //
            return ResponseUtil.get(ResponseEnum.FAIL, "结算失败：该申请单不是'未缴费'状态");
        }

        // 2. 查找住院记录并获取余额
        // 查询的是 hz_status = 0
        InpatientRecord record = inpatientRecordMapper.findActiveRecordByPatientId(dto.getPatientId());
        if (record == null) {
            // 查询的是 hz_status = 1
            record = inpatientRecordMapper.findApplyingDischargeRecordByPatientId(dto.getPatientId());
            if(record == null){
                return ResponseUtil.get(ResponseEnum.FAIL, "结算失败：未找到患者'已申请出院'的住院记录");
            }
        }

        BigDecimal currentBalance = record.getHzBalance();
        Map<String, Object> result = new HashMap<>();

        // 3. 判断押金情况
        if (currentBalance.compareTo(BigDecimal.ZERO) < 0) {
            // 3.1 情况A: 欠费
            result.put("status", "OWES");
            result.put("amount", currentBalance.abs());
            // (要求：前端提示收费员补缴。补缴成功后，收费员 *再次* 调用本接口)
            // (补缴API应调用 recharge_fee 并更新 hz_balance)
            return ResponseUtil.get(ResponseEnum.FAIL, "结算失败：患者尚欠费 " + currentBalance.abs() + " 元" + " "+result);
        }

        // 3.2 情况B: 有余额 (退费)
        if (currentBalance.compareTo(BigDecimal.ZERO) > 0) {
            // 记录退费流水
            RefundDetail refund = new RefundDetail();
            refund.setBrCaseid(dto.getPatientId());
            refund.setBrMoney(currentBalance);
            refund.setBrDate(new Date());
            refund.setBrType("1"); // '1' = 出院结算
            refundDetailMapper.insertSelective(refund);

            result.put("status", "REFUND");
            result.put("amount", currentBalance);
        } else {
            // 3.3 情况C: 余额为 0
            result.put("status", "SETTLED");
            result.put("amount", BigDecimal.ZERO);
        }

        // 4. (结算完成) 将住院押金清零
        InpatientRecord recordUpdate = new InpatientRecord();
        recordUpdate.setId(record.getId());
        recordUpdate.setHzBalance(BigDecimal.ZERO);
        inpatientRecordMapper.updateByPrimaryKeySelective(recordUpdate); //

        // 5. (结算完成) 更新出院申请单状态为 '1' (待确认)
        InpatientDischargeApp appUpdate = new InpatientDischargeApp();
        appUpdate.setId(dto.getDischargeApplicationId());
        appUpdate.setOaStatus(1); // '1' = 待确认/已结算
        dischargeAppMapper.updateByPrimaryKeySelective(appUpdate); //

        return ResponseUtil.get(ResponseEnum.OK, result);
    }

    @Override
    public ResponseUtil listPendingDeposits(PendingDepositQueryDTO queryDTO) {
        PageHelper.startPage(queryDTO.getPageNum(), queryDTO.getPageSize());
        List<InpatientAppVO> deposits
                = applicationMapper.findPendingDeposits(queryDTO);
        PageInfo<InpatientAppVO> pageInfo = new PageInfo<>(deposits);
        return pageInfo.getSize() > 0 ?
                ResponseUtil.get(ResponseEnum.OK, pageInfo)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public ResponseUtil listPendingSettlements(PendingSettleQueryDTO queryDTO) {
        PageHelper.startPage(queryDTO.getPageNum(), queryDTO.getPageSize());
        List<InpatientDischargeAppVO> settlements
                = dischargeAppMapper.findPendingSettlements(queryDTO);
        PageInfo<InpatientDischargeAppVO> pageInfo = new PageInfo<>(settlements);
        return pageInfo.getSize() > 0 ?
                ResponseUtil.get(ResponseEnum.OK, pageInfo)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }
}